#include <iostream>
#include "Shapes.h"

using MathGraphics::Ray;
using MathGraphics::Vector;
using MathGraphics::Point;
using MathGraphics::Transform;
using GraphicsColor::RGB;
using LightingMaterial::Material;

GeometryPrimitives::Sphere::Sphere(const MathGraphics::Transform& objectToWorld, const double radius, 
								   GraphicsColor::RGB* color, const LightingMaterial::Material& material) : Shape(objectToWorld, material)
{
	this->radius = radius;
	col = color;
}

bool GeometryPrimitives::Sphere::intersect(const Ray& r)
{
	Ray ray;
	worldToObj(r, &ray);

	double A = ray.v * ray.v;
	double B = 2 * (ray.v.x * ray.o.x + ray.v.y * ray.o.y + ray.v.z * ray.o.z);
	double C = (ray.o.x * ray.o.x + ray.o.y * ray.o.y + ray.o.z * ray.o.z) - (radius*radius);

	double discrm = (B * B) - (4*A*C);

	//objToWorld(*ray, ray);

	if (discrm < 0)
	{
		return false;
	}

	double root = sqrt(discrm);

	double t0 = (-B - root) / (2 * A);
	double t1 = (-B + root) / (2 * A);

	bool retval = false;
	if (t0 > 0.01f && t0 < ray.t)
	{
		ray.t = t0;
		retval = true;
	}
	if (t1 > 0.01f && t1 < ray.t)
	{
		ray.t = t1;
		retval = true;
	}

	return retval;
}

Vector GeometryPrimitives::Sphere::getNormal(const Vector &point) const
{
	Point p(point.x, point.y, point.z);
	worldToObj(p, &p);
	Point dir(p.x - 0.0, p.y - 0.0, p.z - 0.0);
	objToWorld(dir);

	return Vector(Vector(dir.x, dir.y, dir.z).normalize());
}

